package com.tianji.learning.service.impl;

import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import cn.hutool.poi.excel.StyleSet;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CategoryClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.BooleanUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.config.AliyunContentSecurityTemplate;
import com.tianji.learning.config.AuditResult;
import com.tianji.learning.domain.dto.QuestionFormDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.QuestionAdminPageQuery;
import com.tianji.learning.domain.query.QuestionPageQuery;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.excel.easyexcel.QuestionExcelModel;
import com.tianji.learning.excel.helper.export.ExcelExportHelper;
import com.tianji.learning.excel.helper.export.ExcelExportParams;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import lombok.RequiredArgsConstructor;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author 东哥
 * @since 2025-10-25
 */
@Service
@RequiredArgsConstructor
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements IInteractionQuestionService {
    private final InteractionReplyMapper replyMapper;
    private final UserClient userClient;
    private final SearchClient searchClient;
    private final CourseClient courseClient;
    private final CatalogueClient catalogueClient;
    private final CategoryClient categoryClient;
    private final CategoryCache categoryCache;
    private final AliyunContentSecurityTemplate contentSecurityTemplate;

    @Override
    public void saveQuestion(QuestionFormDTO formDTO) {
        // 0、问题内容合规性检测 TODO
        List<String> checkTexts = Lists.newArrayList(formDTO.getTitle(),formDTO.getDescription());
        AuditResult auditResult = contentSecurityTemplate.textAudit(checkTexts);
        if (!auditResult.isPass()) {
            throw new BadRequestException("问题标题或问题描述不合规！详细：["+auditResult.getReason()+"]");
        }

        // 1、数据拷贝
        InteractionQuestion question = BeanUtils.toBean(formDTO, InteractionQuestion.class);

        // 2、补充用户ID
        question.setUserId(UserContext.getUser());

        // 3、新增
        this.save(question);
    }

    @Override
    public PageDTO<QuestionVO> pageQuery(QuestionPageQuery pageQuery) {
        // 1、参数校验
        Long courseId = pageQuery.getCourseId();
        Long sectionId = pageQuery.getSectionId();
        if (ObjectUtil.isEmpty(courseId) && ObjectUtil.isEmpty(sectionId)) {
            throw new BadRequestException("课程ID和小节ID不能同时为空");
        }

        // 2、分页查询
        // select * from interaction_question where couse_id = ? and section_id = ? and user_id = ? and hidden = 0
        // order by create_time desc limit ?,?
        Page<InteractionQuestion> pageResult = this.lambdaQuery()
                .select(InteractionQuestion.class, tableFieldInfo -> ObjectUtil.notEqual(tableFieldInfo.getColumn(), "description"))
                .eq(ObjectUtil.isNotEmpty(courseId), InteractionQuestion::getCourseId, courseId)
                .eq(ObjectUtil.isNotEmpty(sectionId), InteractionQuestion::getSectionId, sectionId)
                .eq(pageQuery.getOnlyMine(), InteractionQuestion::getUserId, UserContext.getUser())
                .eq(InteractionQuestion::getHidden, false)
                .page(pageQuery.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionQuestion> records = pageResult.getRecords();
        if (ObjectUtil.isEmpty(records)) {
            return PageDTO.empty(pageResult);
        }

        // 3、补充信息查询：查询 提问者信息（非匿名）、查询最近一次回答信息（最近一次回答内容、最近回答者ID）
        // 3.1、收集提问者ID集合、收集最近一次回答ID集合
        /*Set<Long> userIds = records.stream().filter(q -> !q.getAnonymity()).map(InteractionQuestion::getUserId).collect(Collectors.toSet());
        Set<Long> lastAnswerIds = CollStreamUtil.toSet(records, InteractionQuestion::getLatestAnswerId);*/
        Set<Long> userIds = new HashSet<>(records.size());
        Set<Long> lastAnswerIds = new HashSet<>(records.size());
        Set<Long> questionIds = new HashSet<>(records.size());
        for (InteractionQuestion record : records) {
            if (!record.getAnonymity()) {
                userIds.add(record.getUserId());
            }
            lastAnswerIds.add(record.getLatestAnswerId());
            questionIds.add(record.getId());
        }
        lastAnswerIds.remove(null);

        // 3.2、根据最近一次回答ID集合 查询 最近一次回答信息，封装成Map（最近一次回答ID：最近一次回答对象）
        List<InteractionReply> lastReplyList = new ArrayList<>(lastAnswerIds.size());
        if (ObjectUtil.isNotEmpty(lastAnswerIds)) {
            lastReplyList = replyMapper.selectBatchIds(lastAnswerIds);
        }
        /*Map<Long, InteractionReply> replyMap = CollStreamUtil.toIdentityMap(lastReplyList, InteractionReply::getId);
        Set<Long> replyUserIds = lastReplyList.stream().filter(reply -> !reply.getAnonymity()).map(reply -> reply.getUserId()).collect(Collectors.toSet());
        userIds.addAll(replyUserIds);*/
        Map<Long, InteractionReply> replyMap = new HashMap<>(lastReplyList.size());
        if (ObjectUtil.isNotEmpty(lastReplyList)) {
            for (InteractionReply reply : lastReplyList) {
                replyMap.put(reply.getId(), reply);
                if (!reply.getAnonymity()) {
                    userIds.add(reply.getUserId());
                }
            }
        }

        // 3.3、根据提问者ID集合 查询 提问者用户信息，封装成Map（用户ID：用户信息对象）
        List<UserDTO> userInfoList = userClient.queryUserByIds(userIds);
        Map<Long, UserDTO> userInfoMap = new HashMap<>(userInfoList.size());
        if (ObjectUtil.isNotEmpty(userInfoList)) {
            userInfoMap = CollStreamUtil.toIdentityMap(userInfoList, UserDTO::getId);
        }

        // 3.4、分组查询每个问题下未被隐藏的回答数
        // select id,count(1) num from interaction_reply where question_id in (?,?) and hidden = 0 and answer_id = 0 group by question_id
        QueryWrapper<InteractionReply> queryWrapper = Wrappers.<InteractionReply>query()
                .select("question_id as id, count(1) as num")
                .in("question_id", questionIds)
                .eq("hidden", false)
                .eq("answer_id",0)
                .groupBy("question_id");
        List<InteractionReply> list = this.replyMapper.selectList(queryWrapper);
        Map<Long, Integer> unHiddenAnswerNumMap = CollStreamUtil.toMap(list, InteractionReply::getId, InteractionReply::getNum);


        // 4、循环遍历当前页码分页数据，封装vo集合
        List<QuestionVO> voList = new ArrayList<>(records.size());
        for (InteractionQuestion record : records) {
            // 4.1、将po转为vo（拷贝）
            QuestionVO vo = BeanUtils.copyBean(record, QuestionVO.class);
            // 设置未被隐藏的回答数量
            vo.setAnswerTimes(unHiddenAnswerNumMap.getOrDefault(record.getId(),0));

            // 4.2、补充提问者信息（昵称、头像）
            if (!record.getAnonymity()) {
                UserDTO userInfo = userInfoMap.get(record.getUserId());
                if (ObjectUtil.isNotEmpty(userInfo)) {
                    vo.setUserName(userInfo.getName());
                    vo.setUserIcon(userInfo.getIcon());
                }
            }

            // 4.3、补充最近一次回答信息（回答内容、回答者昵称）
            InteractionReply lastReply = replyMap.get(record.getLatestAnswerId());
            if (ObjectUtil.isNotEmpty(lastReply)) {
                vo.setLatestReplyContent(lastReply.getContent());
                if (!lastReply.getAnonymity()) {
                    UserDTO userInfo = userInfoMap.get(lastReply.getUserId());
                    if (ObjectUtil.isNotEmpty(userInfo)) {
                        vo.setLatestReplyUser(userInfo.getName());
                    }
                }
            }

            // 4.4、添加vo到集合
            voList.add(vo);
        }

        // 5、封装分页结果返回
        return PageDTO.of(pageResult, voList);
    }

    @Override
    public QuestionVO queryById(Long id) {
        // 1、根据ID查询问题
        InteractionQuestion question = this.getById(id);
        if (ObjectUtil.isEmpty(question) || question.getHidden()) {
            return null;
        }

        // 2、查询提问者信息
        /*UserDTO userInfo = null;
        if (!question.getAnonymity()) {
            userInfo = userClient.queryUserById(question.getUserId());
        }*/

        // 3、封装Vo返回
        /*QuestionVO vo = BeanUtils.copyBean(question, QuestionVO.class);
        if (ObjectUtil.isNotEmpty(userInfo)) {
            vo.setUserName(userInfo.getName());
            vo.setUserIcon(userInfo.getIcon());
        }*/

        QuestionVO vo = BeanUtils.copyBean(question, QuestionVO.class);
        if (!question.getAnonymity()) {
            UserDTO userInfo = userClient.queryUserById(question.getUserId());
            if (ObjectUtil.isNotEmpty(userInfo)) {
                vo.setUserName(userInfo.getName());
                vo.setUserIcon(userInfo.getIcon());
            }
        }
        return vo;
    }

    @Override
    public PageDTO<QuestionAdminVO> adminPageQuery(QuestionAdminPageQuery pageQuery) {
        // 1、调用ES处理课程名称，得到课程ID集合
        List<Long> couseIds = null;
        if (StrUtil.isNotBlank(pageQuery.getCourseName())) {
            couseIds = searchClient.queryCoursesIdByName(pageQuery.getCourseName());
            if (ObjectUtil.isEmpty(couseIds)) {
                return PageDTO.empty(0L, 0L);
            }
        }

        // 2、分页查询问题列表
        // select * from interaction_question where couse_id in (?) and status = ? and create_time >= ? and create_time <= ?
        // order by create_time desc limit ?,?
        Page<InteractionQuestion> pageResult = this.lambdaQuery()
                .in(ObjectUtil.isNotEmpty(couseIds), InteractionQuestion::getCourseId, couseIds)
                .eq(ObjectUtil.isNotEmpty(pageQuery.getStatus()), InteractionQuestion::getStatus, pageQuery.getStatus())
                .ge(ObjectUtil.isNotEmpty(pageQuery.getBeginTime()), InteractionQuestion::getCreateTime, pageQuery.getBeginTime())
                .le(ObjectUtil.isNotEmpty(pageQuery.getEndTime()), InteractionQuestion::getCreateTime, pageQuery.getEndTime())
                .page(pageQuery.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionQuestion> records = pageResult.getRecords();
        if (ObjectUtil.isEmpty(records)) {
            return PageDTO.empty(pageResult);
        }

        // 3、补充信息查询（章节数据、课程数据、用户数据）
        // 3.0、收集各种业务ID集合
        Set<Long> userIds = new HashSet<>(records.size());
        Set<Long> cIds = new HashSet<>(records.size());
        Set<Long> cataIds = new HashSet<>(records.size());
        for (InteractionQuestion record : records) {
            userIds.add(record.getUserId());
            cIds.add(record.getCourseId());

            cataIds.add(record.getChapterId());
            cataIds.add(record.getSectionId());
        }

        // 3.1、根据用户ID集合查询用户信息，转为Map（用户ID：用户昵称）
        List<UserDTO> userInfoList = userClient.queryUserByIds(userIds);
        Map<Long, String> userInfoMap = new HashMap<>(userIds.size());
        if (ObjectUtil.isNotEmpty(userInfoList)) {
           userInfoMap = CollStreamUtil.toMap(userInfoList, UserDTO::getId, UserDTO::getName);
        }

        // 3.2、根据课程ID集合查询课程信息，转为Map（课程ID：课程信息对象）
        List<CourseSimpleInfoDTO> couseInfoList = courseClient.getSimpleInfoList(cIds);
        Map<Long, CourseSimpleInfoDTO> couseInfoMap = new HashMap<>(cIds.size());
        if (ObjectUtil.isNotEmpty(couseInfoList)) {
            couseInfoMap = CollStreamUtil.toIdentityMap(couseInfoList, CourseSimpleInfoDTO::getId);
        }

        // 3.3、根据章节ID集合查询章节信息，转为Map（章节ID：章节名称）
        List<CataSimpleInfoDTO> cataInfoList = catalogueClient.batchQueryCatalogue(cataIds);
        Map<Long, String> cataInfoMap = new HashMap<>(cataIds.size());
        if (ObjectUtil.isNotEmpty(cataInfoList)) {
            cataInfoMap = CollStreamUtil.toMap(cataInfoList, CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName);
        }

        // 4、循环分页列表数据，封装vo集合
        List<QuestionAdminVO> voList = new ArrayList<>(records.size());

        /*List<CategoryBasicDTO> allOfOneLevelList = categoryClient.getAllOfOneLevel();
        Map<Long, String> allCategoryMap = CollStreamUtil.toMap(allOfOneLevelList, CategoryBasicDTO::getId, CategoryBasicDTO::getName);*/
        for (InteractionQuestion question : records) {
            // 4.1、属性拷贝（po -> vo）
            QuestionAdminVO vo = BeanUtils.copyBean(question, QuestionAdminVO.class);
            vo.setAnswerAmounts(question.getAnswerTimes());

            // 4.2、填充章节名称
            vo.setChapterName(cataInfoMap.getOrDefault(question.getChapterId(),""));
            vo.setSectionName(cataInfoMap.getOrDefault(question.getSectionId(),""));

            // 4.3、填充提问者昵称
            vo.setUserName(userInfoMap.getOrDefault(question.getUserId(),""));

            // 4.4、填充课程名称 和 三级分类信息
            CourseSimpleInfoDTO courseInfo = couseInfoMap.get(question.getCourseId());
            if(ObjectUtil.isNotEmpty(courseInfo)){
                vo.setCourseName(courseInfo.getName());
                // 已知课程三级分类ID ->  三级分类名称 拼接字符串，示例：一级分类/二级分类/三级分类
                /*String firstCataName = allCategoryMap.get(courseInfo.getFirstCateId());
                String secondCataName = allCategoryMap.get(courseInfo.getSecondCateId());
                String thridCataName = allCategoryMap.get(courseInfo.getThirdCateId());
                String categoryName = List.of(firstCataName, secondCataName, thridCataName).stream().collect(Collectors.joining("/"));*/
                vo.setCategoryName(categoryCache.getCategoryNames(courseInfo.getCategoryIds()));
            }

            // 4.5、添加至vo集合
            voList.add(vo);
        }

        // 5、封装分页数据并返回
        return PageDTO.of(pageResult,voList);
    }

    /**
     * 5、根据ID删除互动问题（Day5 - 实战）
     *
     * @param id
     */
    @Override
    @Transactional
    public void deleteById(Long id) {
        // 1.获取当前登录用户
        Long userId = UserContext.getUser();
        // 2.查询当前问题
        InteractionQuestion q = getById(id);
        if (q == null) {
            return;
        }
        // 3.判断是否是当前用户的问题
        if (!q.getUserId().equals(userId)) {
            // 不是，抛出异常
            throw new BadRequestException("无权删除他人的问题");
        }
        // 4.删除问题
        removeById(id);
        // 5.删除回答
        replyMapper.delete(
                new QueryWrapper<InteractionReply>().lambda().eq(InteractionReply::getQuestionId, id)
        );
    }

    /**
     * 6、根据ID修改互动问题（Day5 - 实战）
     *
     * @param id
     * @param questionDTO
     */
    @Override
    public void updateQuestion(Long id, QuestionFormDTO questionDTO) {
        // 1.获取当前登录用户
        Long userId = UserContext.getUser();
        // 2.查询当前问题
        InteractionQuestion q = getById(id);
        if (q == null) {
            throw new BadRequestException("问题不存在");
        }
        // 3.判断是否是当前用户的问题
        if (!q.getUserId().equals(userId)) {
            // 不是，抛出异常
            throw new BadRequestException("无权修改他人的问题");
        }
        // 4.修改问题
        InteractionQuestion question = BeanUtils.toBean(questionDTO, InteractionQuestion.class);
        question.setId(id);
        updateById(question);
    }

    /**
     * 7、管理端根据ID查询互动问题（Day5 - 实战）
     *
     * @param id
     * @return
     */
    @Override
    public QuestionAdminVO queryQuestionByIdAdmin(Long id) {
        // 1.根据id查询问题
        InteractionQuestion question = getById(id);
        if (question == null) {
            return null;
        }
        // 2.转PO为VO
        QuestionAdminVO vo = BeanUtils.copyBean(question, QuestionAdminVO.class);
        // 3.查询提问者信息
        UserDTO user = userClient.queryUserById(question.getUserId());
        if (user != null) {
            vo.setUserName(user.getName());
            vo.setUserIcon(user.getIcon());
        }
        // 4.查询课程信息
        CourseFullInfoDTO cInfo = courseClient.getCourseInfoById(
                question.getCourseId(), false, true);
        if (cInfo != null) {
            // 4.1.课程名称信息
            vo.setCourseName(cInfo.getName());
            // 4.2.分类信息
            vo.setCategoryName(categoryCache.getCategoryNames(cInfo.getCategoryIds()));
            // 4.3.教师信息
            List<Long> teacherIds = cInfo.getTeacherIds();
            List<UserDTO> teachers = userClient.queryUserByIds(teacherIds);
            if (ObjectUtil.isNotEmpty(teachers)) {
                vo.setTeacherName(teachers.stream()
                        .map(UserDTO::getName).collect(Collectors.joining("/")));
            }
        }
        // 5.查询章节信息
        List<CataSimpleInfoDTO> catas = catalogueClient.batchQueryCatalogue(
                List.of(question.getChapterId(), question.getSectionId()));
        Map<Long, String> cataMap = new HashMap<>(catas.size());
        if (ObjectUtil.isNotEmpty(catas)) {
            cataMap = catas.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));
        }
        vo.setChapterName(cataMap.getOrDefault(question.getChapterId(), ""));
        vo.setSectionName(cataMap.getOrDefault(question.getSectionId(), ""));
        // 6.封装VO
        return vo;
    }

    /**
     * 8、管理端隐藏或显示问题（Day5 - 实战）
     *
     * @param id
     * @param hidden
     */
    @Override
    @Transactional
    public void hiddenQuestion(Long id, Boolean hidden) {
        // 1.更新问题
        InteractionQuestion question = new InteractionQuestion();
        question.setId(id);
        question.setHidden(hidden);
        updateById(question);

        // 2.没有answerId，说明自己是回答，需要隐藏回答下的评论
        replyMapper.update(null,
                Wrappers.<InteractionReply>lambdaUpdate()
                        .set(InteractionReply::getHidden, hidden)
                        .eq(InteractionReply::getQuestionId, id)
        );
    }

    /**
     * 9、获取导出数据
     *
     * @param query
     * @return
     */
    @Override
    public List<QuestionExcelModel> getExportDatas(QuestionPageQuery query) {
        // 1、参数校验，课程ID和小节ID不能同时为空
        Long courseId = query.getCourseId();
        Long sectionId = query.getSectionId();
        if (ObjectUtil.isEmpty(courseId) && ObjectUtil.isEmpty(sectionId)) {
            throw new BadRequestException("课程ID和小节ID不能同时为空");
        }

        // 2、分页查询
        // select * from interaction_question where course_id = ? or section_id = ? and user_id = ? and hidden = 0
        // order by ceate_time desc
        List<InteractionQuestion> records = this.lambdaQuery()
                .select(InteractionQuestion.class, tableFieldInfo -> ObjectUtil.notEqual(tableFieldInfo.getColumn(), "description"))
                .eq(ObjectUtil.isNotNull(courseId), InteractionQuestion::getCourseId, courseId)
                .eq(ObjectUtil.isNotNull(sectionId), InteractionQuestion::getSectionId, sectionId)
                .eq(BooleanUtils.isTrue(query.getOnlyMine()), InteractionQuestion::getUserId, UserContext.getUser())
                .eq(InteractionQuestion::getHidden, false)
                .orderByDesc(InteractionQuestion::getCreateTime)
                .list();
        if (ObjectUtil.isEmpty(records)) {
            return Collections.emptyList();
        }

        // 3、补充信息查询，查询 提问者信息（非匿名的）、查询最近一次回答信息
        // 3.1、收集提问者ID集合、收集最近一次回答ID集合
        Set<Long> userIds = new HashSet<>(records.size());
        Set<Long> lastAnswerIds = new HashSet<>(records.size());
        Set<Long> questionIds = new HashSet<>(records.size());
        for (InteractionQuestion record : records) {
            if (!record.getAnonymity()) {
                userIds.add(record.getUserId());
            }
            lastAnswerIds.add(record.getLatestAnswerId());
            questionIds.add(record.getId());
        }

        // 3.2、根据最近一次回答ID集合进行查询 -> 最近一次回答信息，封装成Map （最近一次回答ID：最近一次回答对象）
        List<InteractionReply> latestReplyList = replyMapper.selectBatchIds(lastAnswerIds);
        Map<Long, InteractionReply> replyMap = new HashMap<>(latestReplyList.size());
        if (ObjectUtil.isNotEmpty(latestReplyList)) {
            for (InteractionReply reply : latestReplyList) {
                replyMap.put(reply.getId(), reply);
                if (!reply.getAnonymity()) {
                    userIds.add(reply.getUserId());
                }
            }
        }

        // 3.3、根据提问者ID集合远程调用用户服务 -> 用户信息，封装成Map（用户ID：用户信息）
        Map<Long, UserDTO> userInfoMap = new HashMap<>(userIds.size());
        if (ObjectUtil.isNotEmpty(userIds)) {
            List<UserDTO> userInfoList = userClient.queryUserByIds(userIds);
            if (ObjectUtil.isNotEmpty(userInfoList)) {
                userInfoMap = userInfoList.stream().collect(Collectors.toMap(UserDTO::getId, Function.identity()));
            }
        }

        // 3.4、分组查询每个问题下未被隐藏的回答数
        // select id,count(1) num from interaction_reply where question_id in (?,?) and hidden = 0 and answer_id = 0 group by question_id
        QueryWrapper<InteractionReply> queryWrapper = Wrappers.<InteractionReply>query()
                .select("question_id as id, count(1) as num")
                .in("question_id", questionIds)
                .eq("hidden", false)
                .eq("answer_id",0)
                .groupBy("question_id");
        List<InteractionReply> list = this.replyMapper.selectList(queryWrapper);
        Map<Long, Integer> unHiddenAnswerNumMap = CollStreamUtil.toMap(list, InteractionReply::getId, InteractionReply::getNum);


        // 4、循环遍历分页数据，封装vo集合
        List<QuestionExcelModel> modelList = new ArrayList<>(records.size());
        for (InteractionQuestion record : records) {
            // 4.1、将po转为vo（拷贝）
            QuestionExcelModel model = BeanUtils.toBean(record, QuestionExcelModel.class);
            model.setAnonymityStr(record.getAnonymity() ? "是" : "否");
            // 设置未被隐藏的回答数量
            model.setAnswerTimes(unHiddenAnswerNumMap.getOrDefault(record.getId(),0));

            // 4.2、补充提问者信息（昵称、头像）
            if (!record.getAnonymity()) {
                UserDTO userInfo = userInfoMap.get(record.getUserId());
                if (ObjectUtil.isNotEmpty(userInfo)) {
                    model.setUserName(userInfo.getName());
                }
            }

            // 4.3、补充最近一次回答信息（回答内容、回答者昵称）
            InteractionReply lastReply = replyMap.get(record.getLatestAnswerId());
            if (ObjectUtil.isNotEmpty(lastReply)) {
                model.setLatestReplyContent(lastReply.getContent());
                if (!lastReply.getAnonymity()) {
                    UserDTO userInfo = userInfoMap.get(lastReply.getUserId());
                    if (ObjectUtil.isNotEmpty(userInfo)) {
                        model.setLatestReplyUser(userInfo.getName());
                    }
                }
            }

            // 4.4、添加vo到集合
            modelList.add(model);
        }

        // 5、返回结果集
        return modelList;
    }

    @Override
    public void exportStyle1(HttpServletResponse response, List<QuestionExcelModel> dataList) throws IOException {
        // 基于EasyExcel导出Excel文件
        String fileName = "问题信息表1";
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename=" + new String(fileName.getBytes("gb2312"), "ISO8859-1") + ".xlsx");

        // 基于EasyExcel导出Excel文件
        EasyExcel.write(response.getOutputStream(), QuestionExcelModel.class)
                .sheet("问题列表")
                .doWrite(dataList);
    }

    @Override
    public void exportStyle2(HttpServletResponse response, List<QuestionExcelModel> dataList) throws Exception {
        String[] headerName1 = {"互动问题名称", "回答数量", "创建时间", "是否匿名提问", "提问者昵称", "最新回答信息", "最新回答者昵称"};
        String[] headerKey1 = {"title", "answerTimes", "createTime", "anonymityStr", "userName", "latestReplyContent", "latestReplyUser"};

        String[] headerName2 = {"互动问题名称", "是否匿名提问", "提问者昵称", "最新回答信息", "最新回答者昵称"};
        String[] headerKey2 = {"title", "anonymityStr", "userName", "latestReplyContent", "latestReplyUser"};


        ExcelExportParams exportParams = ExcelExportParams.create(response)
                .addSheet("问题列表1", headerName1, headerKey1, dataList, ExcelExportHelper.YMD_HMS)
                .addSheet("问题列表2", headerName2, headerKey2, dataList);
        exportParams.setFileName("问题信息表2");

        ExcelExportHelper.export(exportParams);
    }

    @Override
    public void exportStyle3(HttpServletResponse response, List<QuestionExcelModel> dataList) {
        ExcelExportParams exportParams = ExcelExportParams.create(response, "questionMsgRecord");
        exportParams.addDataList("问题列表1", dataList, ExcelExportHelper.YMD_HMS);
        exportParams.addDataList("问题列表2", dataList);
        exportParams.setFileName("问题信息表3");
        ExcelExportHelper.export(exportParams);
    }

    @Override
    public void exportStyle4(HttpServletResponse response, List<QuestionExcelModel> dataList) {
        //导出数据，添加数据与sheet顺序对应
        long count = dataList.size();
        Map<String, Object> params = new HashMap<>();
        params.put("count", count);

        Map<String, Object> beanParams = new HashMap<>();
        beanParams.put("cd", params);

        List dataLists = new ArrayList<>();
        dataLists.add(dataList);
        dataLists.add(dataList);
        ExcelExportHelper.export(dataLists, beanParams, "问题信息导出模板.xlsx",
                "问题信息表4.xlsx", response);
    }

    @Override
    public void exportStyle5(HttpServletResponse response, List<QuestionExcelModel> dataList) {
        String[] headerName1 = {"互动问题名称", "回答数量", "创建时间", "是否匿名提问", "提问者昵称", "最新回答信息", "最新回答者昵称"};
        String[] headerKey1 = {"title", "answerTimes", "createTime", "anonymityStr", "userName", "latestReplyContent", "latestReplyUser"};

        String[] headerName2 = {"互动问题名称", "是否匿名提问", "提问者昵称", "最新回答信息", "最新回答者昵称"};
        String[] headerKey2 = {"title", "anonymityStr", "userName", "latestReplyContent", "latestReplyUser"};
        // 通过工具类创建writer
        ExcelWriter writer = ExcelUtil.getBigWriter();
        // 默认未添加alias的属性也会写出，如果想只写出加了别名的字段，可以调用此方法排除之
        writer.setOnlyAlias(true);

        //创建sheet1
        writer.setSheet("sheet1");
        for (int i = 0; i < headerKey1.length; i++) {
            writer.addHeaderAlias(headerKey1[i], headerName1[i]);
            writer.setColumnWidth(i, 24);
        }
        this.setStyle(writer);
        //合并单元格后的标题行，使用默认标题样式
        writer.merge(headerName1.length - 1, "问题列表1");
        // 一次性写出内容，使用默认样式，强制输出标题
        writer.write(dataList, true);

        //关键：清空别名Map，防止两个sheet之间数据干扰
        writer.clearHeaderAlias();

        //创建sheet2
        writer.setSheet("sheet2");
        for (int i = 0; i < headerKey2.length; i++) {
            writer.addHeaderAlias(headerKey2[i], headerName2[i]);
            writer.setColumnWidth(i, 24);
        }
        this.setStyle(writer);
        //合并单元格后的标题行，使用默认标题样式
        writer.merge(headerName2.length - 1, "问题列表2");
        // 一次性写出内容，使用默认样式，强制输出标题
        writer.write(dataList, true);

        //输出excel至浏览器
        ExcelExportHelper.outputFile(response, "问题信息表5.xlsx", writer);
    }

    private void setStyle(ExcelWriter writer) {
        writer.setDefaultRowHeight(32);
        Font headerCellFont = writer.createFont();
        headerCellFont.setFontName("宋体");
        headerCellFont.setFontHeightInPoints((short) 14);
        headerCellFont.setBold(true);

        Font dataCellFont = writer.createFont();
        headerCellFont.setFontName("宋体");
        headerCellFont.setFontHeightInPoints((short) 11);

        StyleSet style = writer.getStyleSet();
        style.getHeadCellStyle().setFont(headerCellFont);
        style.getCellStyle().setFont(dataCellFont);
        // 第二个参数表示是否也设置头部单元格背景
        style.setBackgroundColor(IndexedColors.WHITE1, false);
    }
}
